﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;

namespace BMap
{
    public static class BaiduExtension
    {
        public static MvcHtmlString BaiduMap(this HtmlHelper helper, string mapId, double latitude, double longitude, int zoom)
        {
            return helper.BaiduMap(mapId, latitude, longitude, zoom, null, null);
        }

        public static MvcHtmlString BaiduMap(this HtmlHelper helper, string mapId, double latitude, double longitude, int zoom, IEnumerable<MapMarker> markers)
        {
            return helper.BaiduMap(mapId, latitude, longitude, zoom, markers, null);
        }

        public static MvcHtmlString BaiduMap(this HtmlHelper helper, string mapId, double latitude, double longitude, int zoom, IEnumerable<MapControl> ctrls)
        {
            return helper.BaiduMap(mapId, latitude, longitude, zoom, null, ctrls);
        }

        public static MvcHtmlString BaiduMap(this HtmlHelper helper, string mapId, double latitude, double longitude, int zoom, IEnumerable<MapMarker> markers, IEnumerable<MapControl> ctrls)
        {
            var stringWriter = new StringWriter();
            var writer = new HtmlTextWriter(stringWriter);
            writer.RenderJsInclude(mapId);
            writer.FuncBegin();
            writer.InitMap(mapId, latitude, longitude,zoom);
            writer.RenderMapMarker(mapId, markers);
            writer.RenderMapControl(mapId, ctrls);
            writer.FuncEnd();
            return MvcHtmlString.Create(stringWriter.GetStringBuilder().ToString());
        }

        public static MvcBaiduMap BeginBaiduMap(this HtmlHelper helper, string mapId, double latitude, double longitude, int zoom)
        {
            if (string.IsNullOrEmpty(mapId))
            {
                throw new ArgumentNullException("mapId");
            }
            helper.ViewContext.Writer.RenderJsInclude(mapId);
            helper.ViewContext.Writer.FuncBegin();
            helper.ViewContext.Writer.InitMap(mapId, latitude, longitude, zoom);
            helper.ViewContext.HttpContext.Items["ViewContext_BaiduMapContext"] = new BaiduMapContext(mapId, GetFixedMapId(mapId), latitude, longitude, zoom);
            return new MvcBaiduMap(helper.ViewContext, mapId);
        }

        public static MvcHtmlString RenderMarker(this HtmlHelper helper, params MapMarker[] markers)
        {
            if (markers != null && markers.Length > 0)
                helper.ViewContext.Writer.RenderMapMarker(MapContext.MapID, markers);
            return new MvcHtmlString("");
        }

        public static MvcHtmlString RenderMarker(this HtmlHelper helper, double latitude, double longitude
            , string iconUrl = null, string iconWidth = null, string iconHeight = null
            , string animation = null, bool draggable = false, string onClientClick = null)
        {
            return RenderMarker(helper, new MapMarker
            {
                Latitude = latitude,
                Longitude = longitude,
                IconUrl = iconUrl,
                IconWidth = iconWidth,
                IconHeight = iconHeight,
                Animation = animation,
                Draggable = draggable,
                OnClientClick = onClientClick
            });
        }

        public static MvcHtmlString RenderControl(this HtmlHelper helper, params MapControl[] controls)
        {
            if (controls != null && controls.Length > 0)
                helper.ViewContext.Writer.RenderMapControl(MapContext.MapID, controls);
            return new MvcHtmlString("");
        }

        public static MvcHtmlString RenderControl(this HtmlHelper helper, MapControlType ctrlType, MapControlOption option)
        {
            return RenderControl(helper, new MapControl {ControlType = ctrlType, Option = option});
        }

        public static MvcHtmlString RenderLabel(this HtmlHelper helper, string text, double ptx, double pty,
            double offsetX = 0, double offsetY = 0, object style = null)
        {
            return RenderLabel(helper, new MapLabelOption
            {
                Text = text,
                PointX = ptx,
                PointY = pty,
                OffsetX = offsetX,
                OffsetY = offsetY,
                Style = style
            });
        }

        private static MvcHtmlString RenderLabel(HtmlHelper helper, MapLabelOption option)
        {
            if (option != null)
                helper.ViewContext.Writer.RenderMapLabel(MapContext.MapID, option);
            return new MvcHtmlString("");
        }

        public static MvcHtmlString RenderControl(this HtmlHelper helper, MapControlType ctrlType
            , MapAnchorEnum anchor = MapAnchorEnum.None, int x = 0, int y = 0, string optType = null)
        {
            return RenderControl(helper, ctrlType, new MapControlOption
            {
                Anchor = anchor,
                Type = optType,
                X = x,
                Y = y
            });
        }

        internal static BaiduMapContext MapContext
        {
            get
            {
                var context = HttpContext.Current.Items["ViewContext_BaiduMapContext"] as BaiduMapContext;
                if (context == null)
                {
                    throw new Exception("This extension method must be called in Html.BeginBaiduMap code block. For example:\r\n\r\n@using (Html.BeginBaiduMap(\"map3\", 0,0,13))\r\n{\r\n    @Html.RenderMarker(new MapMarker{Latitude = 0, Longitude = 0, Draggable = true})\r\n}");
                }
                return context;
            }
        }

        internal static void EndMap(ViewContext viewContext)
        {
            viewContext.Writer.Write("    });\r\n</script>");
            viewContext.OutputClientValidation();
            viewContext.RequestContext.HttpContext.Items["ViewContext_BaiduMapContext"] = null;
        }

        internal static string GetFixedMapId(string mapId)
        {
            return Regex.Replace(mapId, "[^a-z0-9A-Z]+", "_");
        }
    }
}